import random
import re

from flask import abort, jsonify
from flask import current_app
from flask import make_response
from flask import request
from flask import session

from info import constants, db
from info import redis_store
from info.models import User
from info.utils.captcha.captcha import captcha
from info.utils.response_code import RET
from . import passport_blue


@passport_blue.route('/login', methods=['POST'])
def login():
    """
    1. 获取参数和判断是否有值
    2. 从数据库查询出指定的用户
    3. 校验密码
    4. 保存用户登录状态
    5. 返回结果
    :return:
    """


@passport_blue.route('/register', methods=['POST'])
def register():
    """
        1. 获取参数和判断是否有值
        2. 从redis中获取指定手机号对应的短信验证码的
        3. 校验验证码
        4. 初始化 user 模型，并设置数据并添加到数据库
        5. 保存当前用户的状态
        6. 返回注册的结果
    """
    # 1. 获取参数和判断是否有值

    mobile = request.json.get('mobile')
    sms_code = request.json.get('sms_code')
    password = request.json.get('password')

    if not all([mobile, sms_code, password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不全')

    try:
        real_sms_code = redis_store.get('sms_code_'+mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='获取本地验证码失败')

    if not real_sms_code:
        return jsonify(errno=RET.NODATA, errmsg='短信验证码过期')

    if sms_code != real_sms_code:
        return jsonify(errno=RET.DATAERR, errmsg='短信验证码错误')

    try:
        redis_store.delete('sms_code_'+mobile)
    except Exception as e:
        current_app.logger.error(e)

    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询mysql数据库错误')
    if user:
        return jsonify(errno=RET.DATAEXIST, errmsg='手机号已注册')

    user = User()
    user.nick_name = mobile
    user.mobile = mobile
    user.password = password

    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg='数据保存错误')

    session['user_id'] = user.id
    session['nick_name'] = user.nick_name
    session['mobile'] = mobile

    return jsonify(errno=RET.OK, errmsg='ok')


@passport_blue.route('/sms_code', methods=['POST'])
def sms_code():
    """
    1. 获取参数
    2. 从redis获取数据
    3. 对比图像验证码的值
    4. 对比成功，自己生成验证码
    5. 保存验证码到redis
    6. 发送短信
    """

    # 1.获取参数
    # 开发中获取json数据使用request.json,可以一步到位获取到字典数据
    mobile = request.json.get('mobile')
    image_code = request.json.get("image_code")
    image_code_id = request.json.get("image_code_id")

    # 校验参数
    # 1.1 验证完整性
    if not all([mobile, image_code, image_code_id]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    # 1.2 验证手机号是否正确
    if not re.match(r'1[3456789][0-9]{9}', mobile):
        return jsonify(errno=RET.PARAMERR, errmsg='手机号码有误')

    # 2. 从redis获取数据
    try:
        real_image_code = redis_store.get("image_code_id_"+image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库错误')

    # 读取redis/myisql一定要判断数据是否为空
    if not real_image_code:
        return jsonify(errno=RET.NODATA, errmsg='验证码已过期')

    # 3. 对比图像验证码的值
    if real_image_code.lower() != image_code.lower():
        return jsonify(errno=RET.DATAERR, errmsg='验证码填写错误')

    # 4. 对比成功，自己生成验证码
    sms_code_str = "%06d" % random.randint(0, 999999)
    current_app.logger.info(sms_code_str)

    # 5. 保存验证码到redis
    try:
        redis_store.setex('sms_code_'+mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code_str)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='存储失败')

    return jsonify(errno=RET.OK, errmsg='短信验证码发送成功')


@passport_blue.route('/image_code')
def get_image_code():

    image_code_id = request.args.get("image_code_id")

    if not image_code_id:
        return abort(403)

    name, text, image_data = captcha.generate_captcha()

    try:
        redis_store.setex('image_code_id_'+image_code_id, constants.IMAGE_CODE_REDIS_EXPIRES, text)
    except Exception as e:
        current_app.logger.error(e)
        return abort(500)

    response = make_response(image_data)
    response.headers['Content-type'] = 'image/jpg'

    return response
